package com.lfs.adapter.service.impl;

import com.lfs.adapter.service.GameOrderInfoService;
import com.lfs.base.util.HttpClientUtil;
import com.lfs.common.constant.Constant;
import com.lfs.common.utils.sign.Md5Utils;
import com.lfs.interfaces.dao.BaseChargeDao;
import com.lfs.interfaces.dto.ResultReturn;
import com.lfs.interfaces.model.AgtAccess;
import com.lfs.interfaces.model.OrderNotify;
import com.lfs.interfaces.model.dto.OrderCharge;
import com.lfs.interfaces.model.dto.OrderDto;
import com.lfs.interfaces.model.dto.OrderNotifyDto;
import com.lfs.interfaces.model.vo.AgtAccessVo;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.*;

@Service
public class GameOrderInfoServiceImpl implements GameOrderInfoService {

    private Logger log = LoggerFactory.getLogger(GameOrderInfoServiceImpl.class);
    @Autowired
    private BaseChargeDao baseDao;

    /**
     * 查询后回写订单
     */
    public Map<String,String> updateOrderAfterQuery(OrderDto dto) {
        log.info("【开始执行更新订单状态并回调,订单号为:{}】",dto.getOrderNo());
        //初始化退款状态为 -1;
        Map<String,String> resultMap = new HashMap<>();
        OrderCharge updateOrder = new OrderCharge();
        BigDecimal chargeMoney = dto.getOutMoney();
        BigDecimal profit = dto.getProfit();
        updateOrder.setOrderNo(dto.getOrderNo());
        updateOrder.setState(dto.getState());
        updateOrder.setCheckState(dto.getCheckState());
        updateOrder.setRemark(dto.getRemark());
        updateOrder.setErrorCode(dto.getErrorCode());
        // 失败订单，退款
        try {
            int updateResult=baseDao.update("GameOrderInfoMapper.updateOrderAfterQuery", updateOrder);
            log.info("【更新订单状态结束】");
            resultMap.put("code", "0");
            resultMap.put("message", "订单状态为成功,更新订单成功");
            log.info("订单号为:{},订单状态为:{}",dto.getOrderNo(),dto.getState()+"准备发送回调给下游!");
            return resultMap;
        } catch (Exception e) {
            resultMap.put("code", "-999");
            resultMap.put("message", "数据库操作异常!");
            log.info("数据库异常!");
            e.printStackTrace();

        }
        return resultMap;
    }

    /**
     * 更改订单状态,不涉及退款处理
     * @param dto
     * @return
     */
    public Map<String,String> updateOrderState(OrderDto dto) {
        log.info("【更改订单状态开始:{}】",dto.getOrderNo());
        Map<String,String> resultMap = new HashMap<>();
        OrderCharge updateOrder = new OrderCharge();
        updateOrder.setOrderNo(dto.getOrderNo());
        updateOrder.setState(dto.getState());
        updateOrder.setCheckState(dto.getCheckState());
        updateOrder.setRemark(dto.getRemark());
        updateOrder.setUpOrderNo(dto.getUpOrderNo());
        updateOrder.setErrorCode(dto.getErrorCode());
        try {
            baseDao.update("GameOrderInfoMapper.updateOrderAfterQuery", updateOrder);

        } catch (Exception e) {
            resultMap.put("code", "-999");
            resultMap.put("message", "数据库操作异常!");
            log.info("【更改订单状态异常:{}】",dto.getOrderNo());
            e.printStackTrace();

        }
        log.info("【更改订单状态结束:{}】",dto.getOrderNo());
        return resultMap;
    }
    /**
     * 发送回调
     */
    public void sendNotify(OrderNotifyDto dto) {
        try {
            // 1、回写回调表订单状态
            OrderNotify notify = new OrderNotify();
            notify.setAgtPhone(dto.getAgtPhone());
            notify.setReqStreamId(dto.getReqStreamId());
            notify.setState(dto.getState());
            log.info("回调准备发送:" + dto.getReqStreamId() + "|" + dto.getState());
            // 2、发送一次回调
            List<OrderNotify> orderNotifies = baseDao.selectList("GameOrderInfoMapper.getOrderNotifyInfo", notify);
            notify.setCount(1);
            ResultReturn<AgtAccessVo> accessReturn = getAgtAccessByAgtPhone(notify.getAgtPhone());
            if (accessReturn.getStatus().equals(Constant.SUCCESS) && orderNotifies.size() > 0) {
                OrderNotify orderNotifyInfo = orderNotifies.get(0);
                if (orderNotifyInfo.getNotifyUrl() != null && orderNotifyInfo.getNotifyUrl() != "") {
                    AgtAccessVo vo = accessReturn.getData();
                    String notifyResult = "0";
                    // 其他统一回调
                    orderNotifyInfo.setState(dto.getState());
                    notifyResult = sendNotifyRuitone(orderNotifyInfo, vo.getAppKey());

                    log.info("回调发送完成:" + dto.getReqStreamId() + "|" + dto.getState());
                    if (notifyResult.equals("0")) {
                        // 客户方返回接收成功
                        notify.setFlag(2);
                    } else {
                        // 客户方返回接收失败
                        notify.setFlag(2);
                    }
                    // 3、回写回调表发送状态
                    baseDao.update("GameOrderInfoMapper.updateOrderNotifyAfter", notify);
                }
            } else {
                log.error("【回调状态不成功或者未找到下游回调地址】");
            }
            // }
        } catch (Exception e) {
            log.error(dto.getReqStreamId() + " 回调下游异常:" + e.getMessage(), e);
        }
    }

    public ResultReturn<AgtAccessVo> getAgtAccessByAgtPhone(String agtPhone) {
        try {
            List<AgtAccess> accesses = baseDao.selectList("GameOrderInfoMapper.getAgtAccessByAgtPhone", agtPhone);
            if (accesses.size() > 0) {
                AgtAccessVo vo = new AgtAccessVo();
                vo.setAgtNo(accesses.get(0).getAgtNo());
                vo.setAppId(accesses.get(0).getAppId());
                vo.setAppKey(accesses.get(0).getAppKey());
                vo.setId(accesses.get(0).getId());
                return new ResultReturn<AgtAccessVo>().setStatus(Constant.SUCCESS).setData(vo, new OrderDto());
            } else {
                return new ResultReturn<AgtAccessVo>().setStatus(Constant.FAILED).setData(null, new OrderDto());
            }
        } catch (Exception e) {
            return new ResultReturn<AgtAccessVo>().setStatus(Constant.EXCEPTION).setData(null, new OrderDto());
        }
    }

    /**
     * 拼签名串
     */
    public static String getSignStr(Map<String, Object> paramMap) {
        Map<String, Object> map = new TreeMap<String, Object>(new Comparator<String>() {
            public int compare(String obj1, String obj2) {
                // 降序排序
                return obj1.compareTo(obj2);
            }
        });
        map.putAll(paramMap);

        StringBuffer bf = new StringBuffer();
        Set<String> keySet = map.keySet();
        Iterator<String> iter = keySet.iterator();
        boolean flag = true;
        while (iter.hasNext()) {

            String key = iter.next();
            System.out.println(key + ":" + map.get(key));
            if (flag) {
                bf.append(key).append("=").append(map.get(key));
            } else {
                bf.append("&").append(key).append("=").append(paramMap.get(key));
            }
            flag = false;
        }
        return bf.toString();
    }

    /**
     * 发送回调（统一逻辑规则）
     */
    public String sendNotifyRuitone(OrderNotify orderNotifyInfo, String key) {
        String sign = orderNotifyInfo.getAgtPhone() + orderNotifyInfo.getReqStreamId() + orderNotifyInfo.getState()
                + key;
        String notifyUrl = orderNotifyInfo.getNotifyUrl() + "?agtPhone=" + orderNotifyInfo.getAgtPhone()
                + "&reqStreamId=" + orderNotifyInfo.getReqStreamId() + "&state=" + orderNotifyInfo.getState() + "&sign="
                + Md5Utils.getSignatureByMD5(sign).toLowerCase();
        log.info("SendNotifyUrl=[" + notifyUrl + "]");
        HttpGet httpGet = new HttpGet(notifyUrl);
        httpGet.addHeader("Content-Type", "application/json; charset=utf-8");
        httpGet.addHeader("Accept", "application/json");
        CloseableHttpResponse response = null;
        String result = null;
        try {
            response = HttpClientUtil.getSyncClient().execute(httpGet);
            HttpEntity respEntity = response.getEntity();
            result = EntityUtils.toString(respEntity);
        } catch (Exception e) {
            e.printStackTrace();
            log.error("SendNotifyResult:reqStreamId=[" + orderNotifyInfo.getReqStreamId() + "]exception=["
                    + e.toString() + "]");
        }
        log.info("SendNotifyResult:reqStreamId=[" + orderNotifyInfo.getReqStreamId() + "]result=[" + result + "]");
        return result;
    }

    public void updateOrderAfterNotify(OrderDto orderDto) {
        updateOrderAfterQuery(orderDto);
        // baseDao.update("GameOrderInfoMapper.updateOrderAfterNotify",orderDto);
    }

    public List<OrderCharge> getValidOrderForConfirmByBuscodeAndOrderNo(OrderCharge order) {
        return baseDao.selectList("GameOrderInfoMapper.getValidOrderForConfirmByBuscodeAndOrderNo", order);
    }

    public String getAgtnoByAgtPhone(String agtPhone)
    {
        return baseDao.selectOne("GameOrderInfoMapper.getAgtnoByAgtPhone",agtPhone);
    }

    public OrderDto getOrderInfo(String orderNo) {
        return baseDao.selectOne("GameOrderInfoMapper.getOrderInfoByOrderNo",orderNo);
    }

    public int updateChannelStatus(String channelNum){
        return baseDao.update("ChannelSupplierMapper.updateChannelStatus",channelNum);
    }

    public List<Map<String, Object>> getAdapter(Map<String, Object> paramMap) {

        List<Map<String, Object>> adapterList = baseDao.selectList("GameOrderInfoMapper.getAdapterList", paramMap);
        return adapterList;
    }

    public int insertRechargeOrder(OrderCharge orderInfo) {
        return baseDao.insert("GameOrderInfoMapper.insertRechargeOrder", orderInfo);
    }

    public Map<String,Object> getIfExistOrder(String downOrderNo) {
        return  baseDao.selectOne("GameOrderInfoMapper.getIfExistOrder",downOrderNo);
    }

    public Map<String, Object> getUpProductNo(long productCode,String upChannel) {
        Map<String,Object> map=new HashMap<String, Object>();
        map.put("productCode", productCode);
        map.put("upChannel", upChannel);
        return baseDao.selectOne("GameOrderInfoMapper.getUpProductNo",map);
    }

}
